# -*- coding: utf-8 -*-
# created on 2017/01/05

from mathsolver.functions.base import *
from mathsolver.functions.base.base import new_latex
from mathsolver.functions.mathematica.mathematicaSolve import MathematicaSolve
from mathsolver.functions.xiangliang.basic import (XLJiHeConditionEqTransform, XLJudgeAxis,
                                                   XLXiangs, XLAxisConditionEqTransform, xl_judge_sanjiao_vector,
                                                   XLSanJiaoEqsKnownUpdate, xl_solutions_subs,
                                                   VectorAxisKnownUpdate, VectorAbsKnownUpdate)
from mathsolver.functions.xiangliang.Vector_Fundamental import vector_axis_names, vector_get_abs, vector_get_angles


class XLGetVariable001(BaseFunction):
    def solver(self, *args):
        return self


class XLGetVariable002(BaseFunction):
    """
    向量法：求参数：含equations
    已知向量\\overrightarrow{a}=(1,m),\\overrightarrow{b}=(3,-2),
    (\\overrightarrow{a}+\\overrightarrow{b})⊥\\overrightarrow{b},则m=()
    """
    def solver(self, *args):
        assert len(args) == 1
        known = self.known
        assert 'Vequations' in known
        veqs = known['Vequations']
        assert veqs
        targets = args[0].sympify()
        judge_eqs = []
        judge_eqs.extend(veqs)
        try:
            for target in targets:
                judge_eqs.append([target, S.Zero])
        except Exception:
            judge_eqs.append([targets, S.Zero])
            targets = [targets]
        flag = xl_judge_sanjiao_vector(judge_eqs)
        assert not flag
        flag = XLJudgeAxis(known).solver(targets).output[0].sympify()
        assert flag
        vectors = XLXiangs(known).solver(targets).output[0].sympify()
        vectors_axis_names = vector_axis_names(vectors)
        stepsolver = VectorAxisKnownUpdate(known).solver(vectors_axis_names)
        self.steps += stepsolver.steps
        new_known = stepsolver.output[0]
        condition_veqs = []
        if self.known['inequations']:
            for ineq in self.known['inequations']:
                condition_veqs.append(ineq)
        if self.known['equations']:
            for eq in self.known['equations']:
                condition_veqs.append(eq)
        for eq in veqs:
            if len(eq) == 3:
                new_eqs = XLAxisConditionEqTransform(new_known).solver(BaseIneq(eq)).output[0].sympify()
            else:
                new_eqs = XLAxisConditionEqTransform(new_known).solver(BaseEq(eq)).output[0].sympify()
            condition_veqs.extend(new_eqs)
        target_belongs = {}
        for target in targets:
            if self.search(target):
                target_belongs[target] = self.search(target)
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs), BaseVariables(targets),
                                              target_belongs).output[0]
        self.steps.append(["", "解得: %s" % (solutions.printing())])
        answers = {}
        for target in targets:
            target_values = xl_solutions_subs(solutions, target)
            self.steps.append(
                ["", "∴%s" % " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])])
            answers[target] = target_values
        self.output.append(BaseSymbolValue(answers))
        self.label.add("平面向量-坐标法")
        return self


class XLGetVariable003(BaseFunction):
    """
    # 向量法：向量运算：含equations
    1.已知\\overrightarrow{OA}=(-1,t),\\overrightarrow{OB}=(2,2),\\overrightarrow{BA}*\\overrightarrow{BO}=0,则实数t的值为.
    """
    def solver(self, *args):
        assert len(args) == 1
        known = self.known
        assert 'Vequations' in known
        veqs = known['Vequations']
        assert veqs
        target = args[0].sympify()
        judge_eqs = []
        judge_eqs.extend(veqs)
        judge_eqs.append([target, S.Zero])
        flag = xl_judge_sanjiao_vector(judge_eqs)
        assert flag
        stepsolver = XLSanJiaoEqsKnownUpdate(known).solver(judge_eqs)
        self.steps += stepsolver.steps
        new_known = stepsolver.output[0]
        condition_veqs = []
        for eq in veqs:
            new_eqs = XLAxisConditionEqTransform(new_known).solver(BaseEq(eq)).output[0].sympify()
            for new_eq in new_eqs:
                condition_veqs.append(new_eq)
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs)).output[0]
        self.steps.append(["", "解得: %s" % solutions.printing()])
        target_values = xl_solutions_subs(solutions, target)
        self.steps.append(
            ["", "∴ %s" % " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])])
        self.output.append(BaseSymbolValue({target: target_values}))
        self.label.add("平面向量-坐标法")
        return self


class XLGetVariable004(BaseFunction):
    """
    # 几何法：求参数：含equations
    # 已知\\overrightarrow{a}与\\overrightarrow{b}为两个垂直的单位向量,k为实数,
    # 若向量\\overrightarrow{a}+\\overrightarrow{b}与向量k\\overrightarrow{a}-\\overrightarrow{b}垂直,则k=().
    """
    def solver(self, *args):
        assert len(args) == 1
        known = self.known
        assert 'Vequations' in known
        veqs = known['Vequations']
        assert veqs
        target = args[0].sympify()
        flag = XLJudgeAxis(known).solver(target).output[0].sympify()
        assert not flag
        vectors = XLXiangs(known).solver(target).output[0].sympify()
        stepsolver = VectorAbsKnownUpdate(known).solver(vectors)
        self.steps += stepsolver.steps
        condition_veqs = []
        abs_symbols = []
        c_angle_symbols = []
        for eq in veqs:
            if len(eq) == 2:
                new_eq = XLJiHeConditionEqTransform(known).solver(BaseEq(eq)).output[0].sympify()
            else:
                new_eq = XLJiHeConditionEqTransform(known).solver(BaseIneq(eq)).output[0].sympify()
            condition_veqs.append(new_eq)
            if len(eq) == 2:
                expr = new_eq[0] - new_eq[1]
            else:
                expr = new_eq[0] - new_eq[2]
            expr_abss = vector_get_abs(expr)
            if expr_abss:
                for expr_Abs in expr_abss:
                    abs_symbols.append(expr_Abs)
            expr_c_angles = vector_get_angles(expr)
            if expr_c_angles:
                for expr_CAngle in expr_c_angles:
                    c_angle_symbols.append(expr_CAngle)
        abs_symbols = set(abs_symbols)
        abs_symbols = list(abs_symbols)
        if abs_symbols:
            for Abs_symbol in abs_symbols:
                condition_veqs.append([Abs_symbol, '>=', S.Zero])
        c_angle_symbols = set(c_angle_symbols)
        c_angle_symbols = list(c_angle_symbols)
        if c_angle_symbols:
            for CAngle_symbol in c_angle_symbols:
                condition_veqs.append([CAngle_symbol, '>=', -1])
                condition_veqs.append([CAngle_symbol, '<=', 1])
        self.steps.append(["", "依题意，得"])
        if len(condition_veqs) == 1:
            self.steps.append(["", "%s" % BaseEq(condition_veqs[0]).printing()])
        else:
            self.steps.append(["", "%s" % BaseIneqs(condition_veqs).printing()])
        solutions = MathematicaSolve().solver(BaseIneqs(condition_veqs)).output[0]
        self.steps.append(["", "解得: %s" % solutions.printing()])
        target_values = xl_solutions_subs(solutions, target)
        self.steps.append(
            ["", "∴ %s" % " 或 ".join(["%s = %s" % (new_latex(target), new_latex(v)) for v in target_values])])
        self.output.append(BaseSymbolValue({target: target_values}))
        self.label.add("平面向量-几何法")
        return self


class XLGetVariable(BaseFunction):
    CLS = [XLGetVariable002, XLGetVariable003, XLGetVariable004]

    def solver(self, *args):
        known = self.known
        r = None
        for cl in XLGetVariable.CLS:
            try:
                new_known = dict(known)
                r = cl(new_known, verbose=True).solver(*args)
                break
            except Exception:
                pass
        if not r:
            raise 'try fail'
        return r
